package com.nd.android.musicboxlibrary.business.db.dao;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.google.gson.Gson;
import com.nd.android.musicboxlibrary.R;
import com.nd.android.musicboxlibrary.business.bean.Album;
import com.nd.android.musicboxlibrary.business.bean.MusicInfo;
import com.nd.android.musicboxlibrary.business.comm.MagicNumber;
import com.nd.android.musicboxlibrary.business.db.MusicBoxDatabase;
import com.nd.android.musicboxlibrary.business.db.parsers.AlbumDbParser;
import com.nd.android.musicboxlibrary.business.db.parsers.MusicDbParser;
import com.nd.android.musicboxlibrary.business.db.table.AlbumColumns;
import com.nd.android.musicboxlibrary.business.db.table.VipInfoColumns;
import com.nd.android.musicboxlibrary.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据相关业务封装
 * 
 * @author 慕容秋 (muroqiu@qq.com)
 */
public final class DbManager implements MagicNumber {
    private Context mContext;

    private SQLiteDatabase mDb;

    private static DbManager dbManager = null;

    // private final static String sampleDb = "mbx_sample.db3";

    public static final String DATABASE_NAME_SUFFIX = "mbx_music_box_";

    private static String mDbName = "";

    private static String mUid = "";

    // 专辑
    public static final String TABLE_ALBUM = "Album";

    // 相册
    public static final String TABLE_MUSIC = "Music";

    /**
     * 获取 DbManager 实例 <br>
     * Created 2014年9月16日 上午12:14:39
     * 
     * @param context
     *            上下文句柄
     * @param uid
     *            用户ID
     * @return DbManager
     * @author wat.ztag
     */
    public static DbManager getInstance(Context context, String uid) {
        if (dbManager == null || !mUid.equals(uid)) {
            dbManager = new DbManager(context, uid);
        }

        return dbManager;
    }

    /**
     * Creates a new instance of DbManager. <br>
     * Created 2014年9月16日 上午12:14:44
     * 
     * @param context
     *            上下文句柄
     * @param uid
     *            用户ID
     */
    private DbManager(Context context, String uid) {
        closeDB();
        mUid = uid;
        mContext = context.getApplicationContext();
        mDbName = DATABASE_NAME_SUFFIX + uid + ".db3";
        createDb(mDbName);

        MusicBoxDatabase helper = new MusicBoxDatabase(context, mDbName);
        mDb = helper.getWritableDatabase();
    }

    /**
     * 创建数据库 <br>
     * Created 2014年9月16日 上午12:14:48
     * 
     * @param ADBName
     *            数据库名称
     * @author wat.ztag
     */
    private void createDb(String ADBName) {
        File Afile = mContext.getDatabasePath(ADBName);
        if (!Afile.exists()) {
            try {
                Afile.getParentFile().mkdirs();
                int byteread = 0;
                // InputStream inStream = mContext.getAssets().open(sampleDb);// 载模板
                InputStream inStream = mContext.getResources().openRawResource(R.raw.mbx_sample);// 载模板
                FileOutputStream fs = new FileOutputStream(Afile.getPath());
                byte[] buffer = new byte[n1024];
                while ((byteread = inStream.read(buffer)) != -1) {
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
                fs.close();
            } catch (Exception e) {
                // System.out.println("复制单个文件操作出错");
                e.printStackTrace();
                Log.d(e.getMessage());
            }
        }
    }

    /**
     * 关闭数据库 <br>
     * Created 2014年9月16日 上午12:14:51
     * 
     * @author wat.ztag
     */
    public void closeDB() {
        if (mDb != null && mDb.isOpen()) {
            mDb.close();
        }
    }

    /**
     * 关闭数据库游标 <br>
     * Created 2014年9月16日 上午12:14:54
     * 
     * @param cursor
     *            游标
     * @author wat.ztag
     */
    private void closeCursor(Cursor cursor) {
        if (cursor != null) {
            cursor.close();
        }
    }

    /**
     * 写入专辑列表 <br>
     * Created 2014年9月16日 上午12:14:58
     * 
     * @param albumList
     *            专辑列表
     * @author wat.ztag
     */
    public void setAlbumList(List<Album> albumList) {
        if (albumList.isEmpty()) {
            return;
        }

        // // 删除服务端已没有的专辑数据
        // List<Album> cacheList = getAlbumList();
        // if (!cacheList.isEmpty()) {
        // for (Album objCache : cacheList) {
        // boolean isValid = false;
        // for (Album obj : albumList) {
        // if (objCache.getId() == obj.getId()) {
        // isValid = true;
        // break;
        // }
        // }
        //
        // if (!isValid) {
        // mDb.delete(TABLE_ALBUM, "Fid = " + objCache.getId(), null);
        // }
        //
        // }
        // }

        mDb.delete(TABLE_ALBUM, null, null);

        for (Album obj : albumList) {
            ContentValues values = new AlbumDbParser().toContentValues(obj);
            mDb.replace(TABLE_ALBUM, null, values);
        }
    }

    /**
     * 获取专辑列表 <br>
     * Created 2014年9月16日 上午12:15:00
     * 
     * @return List<Album>
     * @author wat.ztag
     */
    public List<Album> getAlbumList() {
        List<Album> result = new ArrayList<Album>();

        Cursor cursor = mDb.query(TABLE_ALBUM, null, null, null, null, null, AlbumColumns.DESC
                + " DESC");
        while (cursor.moveToNext()) {
            Album obj = new AlbumDbParser().parse(cursor);
            result.add(obj);
            Log.d(new Gson().toJson(obj).toString());
        }
        closeCursor(cursor);

        return result;
    }

    /**
     * 写入音乐列表 <br>
     * Created 2014年9月16日 上午12:15:03
     * 
     * @param musicList
     *            音乐列表
     * @author wat.ztag
     */
    public void setMusicList(List<MusicInfo> musicList) {
        if (musicList.isEmpty()) {
            return;
        }

        mDb.delete(TABLE_MUSIC, null, null);

        // // 删除服务端已没有的歌曲数据
        // List<MusicInfo> cacheList = getMusicList();
        // if (!cacheList.isEmpty()) {
        // for (MusicInfo objCache : cacheList) {
        // boolean isValid = false;
        // for (MusicInfo obj : musicList) {
        // if (objCache.getId() == obj.getId()) {
        // isValid = true;
        // break;
        // }
        // }
        //
        // if (!isValid) {
        // mDb.delete(TABLE_MUSIC, "Fid = " + objCache.getId(), null);
        // }
        //
        // }
        // }

        // 更新本地缓存
        for (MusicInfo obj : musicList) {
            ContentValues values = new MusicDbParser().toContentValues(obj);
            mDb.replace(TABLE_MUSIC, null, values);
        }
    }

    /**
     * 获取音乐列表 <br>
     * Created 2014年9月16日 上午12:15:14
     * 
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicList() {
        return getMusicList("ORDER BY Music.Fid;");
    }

    /**
     * 获取音乐列表 <br>
     * Created 2014年9月16日 上午12:15:10
     * 
     * @param sqlWhere
     *            Where参数
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    private List<MusicInfo> getMusicList(String sqlWhere) {
        List<MusicInfo> result = new ArrayList<MusicInfo>();

        String sql = "SELECT Music.*, " + " Album.Name as AlbumName,  " + " Album.BgFid "
                + " FROM Music LEFT OUTER JOIN Album ON Music.AlbumId=Album.Fid " + sqlWhere;
        Log.d(sql);
        Cursor cursor = mDb.rawQuery(sql, null);

        while (cursor.moveToNext()) {
            MusicInfo obj = new MusicDbParser().parse(cursor);
            result.add(obj);
        }
        closeCursor(cursor);

        return result;
    }

    /**
     * 查找音乐 <br>
     * Created 2014年9月16日 上午12:15:06
     * 
     * @param id
     *            音乐ID
     * @return MusicInfo
     * @author wat.ztag
     */
    public MusicInfo findMusic(long id) {
        MusicInfo result = null;

        String sql = "SELECT Music.*, " + " Album.Name as AlbumName,  " + " Album.BgFid "
                + " FROM Music LEFT OUTER JOIN Album ON Music.AlbumId=Album.Fid "
                + " WHERE Music.Fid = " + id;
        Log.d(sql);
        Cursor cursor = mDb.rawQuery(sql, null);

        while (cursor.moveToNext()) {
            result = new MusicDbParser().parse(cursor);
        }
        closeCursor(cursor);

        return result;
    }

    /**
     * 获取专辑歌曲列表 <br>
     * Created 2014年9月16日 上午12:15:17
     * 
     * @param ablumId
     *            专辑ID
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfAlbum(long ablumId) {
        return getMusicList("WHERE AlbumId = " + ablumId + " ORDER BY Music.Fid;");
    }

    /**
     * 获取最近播放歌曲列表 <br>
     * Created 2014年9月16日 上午12:15:23
     * 
     * @param limit
     *            limit参数
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfLastPlayed(int limit) {
        return getMusicList("WHERE OrderLastPlay > 0 ORDER BY OrderLastPlay DESC LIMIT " + limit
                + ";");
    }

    /**
     * 获取歌曲下载列表 <br>
     * Created 2014年9月16日 上午12:15:26
     * 
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfDownLoad() {
        return getMusicList("WHERE OrderDownLoad > 0 ORDER BY OrderDownLoad;");
    }

    /**
     * 获取我喜欢的歌曲列表 <br>
     * Created 2014年9月16日 上午12:15:29
     * 
     * @param limit
     *            limit参数
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfFav(int limit) {
        return getMusicList("WHERE OrderFav > 0 ORDER BY OrderFav DESC LIMIT " + limit + ";");
    }

    /**
     * 获取我喜欢的未下载歌曲列表 <br>
     * Created 2014年9月16日 上午12:15:32
     * 
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfFavForDownLoad() {
        return getMusicList("WHERE OrderFav > 0 AND OrderDownLoad = 0 ORDER BY OrderFav;");
    }

    /**
     * 获取播放列表 <br>
     * Created 2014年9月16日 上午12:15:35
     * 
     * @param limit
     *            limit参数
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> getMusicListOfPlaying(int limit) {
        return getMusicList("WHERE OrderPlaying > 0 ORDER BY OrderPlaying LIMIT " + limit + ";");
    }

    /**
     * 记录播放列表 <br>
     * Created 2014年9月16日 上午12:15:37
     * 
     * @param musicInfoList
     *            音乐列表
     * @author wat.ztag
     */
    public void replaceMusicListOfPlaying(List<? extends MusicInfo> musicInfoList) {
        mDb.beginTransaction();
        execSql("UPDATE Music SET OrderPlaying = 0;");

        String sql = "";
        int size = musicInfoList.size();
        try {
            for (int i = 0; i < size; i++) {
                sql = "UPDATE Music SET OrderPlaying = " + (i + 1) + " WHERE Fid = "
                        + musicInfoList.get(i).getId() + "; ";
                execSql(sql);
            }
            mDb.setTransactionSuccessful();
        } finally {
            mDb.endTransaction();
        }

    }

    /**
     * 记录最近播放歌曲 <br>
     * Created 2014年9月16日 上午12:15:40
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void addMusic2LastPlayed(long musicId) {
        execSql("UPDATE Music SET OrderLastPlay = " + System.currentTimeMillis() + " WHERE Fid = "
                + musicId + ";");
    }

    /**
     * 喜欢音乐 <br>
     * Created 2014年9月16日 上午12:15:43
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void likeMusic(long musicId) {
        execSql("UPDATE Music SET OrderFav = " + System.currentTimeMillis() + " WHERE Fid = "
                + musicId + ";");
    }

    /**
     * 不喜欢音乐 <br>
     * Created 2014年9月16日 上午12:15:46
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void unLikeMusic(long musicId) {
        execSql("UPDATE Music SET OrderFav = 0 WHERE Fid = " + musicId + ";");
    }

    /**
     * 加入下载音乐 <br>
     * Created 2014年9月16日 上午12:15:50
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void addMusic2DownloadList(long musicId) {
        execSql("UPDATE Music SET OrderDownLoad = " + System.currentTimeMillis() + " WHERE Fid = "
                + musicId + ";");
    }

  /**
  * 加入下载音乐 <br>
  * Created 2014年11月20日 下午17:15:50
  * 
  * @param musicId
  *            音乐ID
  * @author jiangwb
  */
 public void addMusic2DownloadList(long musicId , boolean isDownloadHQ) {
     execSql("UPDATE Music SET OrderDownLoad = " + System.currentTimeMillis()
    		 +" , IsHQ =  " + (isDownloadHQ?1:0)  + " WHERE Fid = "
             + musicId + ";");
 }
    
    /**
     * 从下载列表中移除音乐 <br>
     * Created 2014年9月16日 上午12:15:52
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void removeMusicFromDownloadList(long musicId) {
        execSql("UPDATE Music SET OrderDownLoad = 0, SizeDownLoaded = 0 WHERE Fid = " + musicId + ";");
    }

    /**
     * 设置音乐下载完成 <br>
     * Created 2014年9月16日 上午12:15:59
     * 
     * @param musicId
     *            音乐ID
     * @author wat.ztag
     */
    public void setMusicDownLoaded(MusicInfo info) {
    	if(info.isHQ() && info.getHQId() > 0){
    		execSql("UPDATE Music SET SizeDownLoaded = HQSize WHERE Fid = " + info.getId() + ";");
    	}else{
    		execSql("UPDATE Music SET SizeDownLoaded = Size WHERE Fid = " + info.getId() + ";");
    	}    	
    }

    /**
     * 搜索歌曲 <br>
     * Created 2014年9月16日 上午12:16:01
     * 
     * @param keyWord
     *            搜索关键字
     * @return List<MusicInfo>
     * @author wat.ztag
     */
    public List<MusicInfo> searchMusicList(String keyWord) {
        return getMusicList("WHERE Music.Name like \"%" + keyWord + "%\" ORDER BY Fid;");
    }


    /**************************************************************************************************/
    /**
     * 音乐VIP信息 数据库操作
     */



    public long getVipEndTime() {
        final String uid = mUid;

        Cursor cursor = null;
        long time = -1;
        try {
            cursor = mDb.query( VipInfoColumns.TABLE_NAME,
                    new String[] { VipInfoColumns.END_TIME },
                    VipInfoColumns.UID + "=?",
                    new String[] { uid }, null, null, null );
            if ( cursor.moveToFirst() ) {
                time = cursor.getLong( cursor.getColumnIndexOrThrow( VipInfoColumns.END_TIME ) );
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if ( cursor != null ) {
                if ( !cursor.isClosed() ) cursor.close();
                cursor = null;
            }
        }
        return  time;
    }

    public void insertOrUpdateVipEndTime(long endTime) {
        final String uid = mUid;

        ContentValues values = new ContentValues();
        values.put( VipInfoColumns.END_TIME, endTime );

        int updated = mDb.update( VipInfoColumns.TABLE_NAME, values,
                VipInfoColumns.UID + "=?",
                new String[] { uid } );

        if ( updated <= 0 ) {
            values.put( VipInfoColumns.UID, uid );
            mDb.insert( VipInfoColumns.TABLE_NAME, null, values );
        }
    }

    public boolean isVipIntercepted() {
        final String uid = mUid;

        Cursor cursor = null;
        boolean intercepted = false;
        try {
            cursor = mDb.query( VipInfoColumns.TABLE_NAME,
                    new String[] { VipInfoColumns.INTERCEPTED },
                    VipInfoColumns.UID + "=?",
                    new String[] { uid }, null, null, null );
            if ( cursor.moveToFirst() ) {
                intercepted = cursor.getInt( cursor.getColumnIndexOrThrow( VipInfoColumns.INTERCEPTED ) ) == VipInfoColumns.TRUE;
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if ( cursor != null ) {
                if ( !cursor.isClosed() ) cursor.close();
                cursor = null;
            }
        }
        return  intercepted;
    }

    public void markVipIntercepted(boolean intercepted) {
        final String uid = mUid;

        ContentValues values = new ContentValues();
        values.put( VipInfoColumns.INTERCEPTED, intercepted ? VipInfoColumns.TRUE : VipInfoColumns.FALSE );

        mDb.update( VipInfoColumns.TABLE_NAME, values,
                VipInfoColumns.UID + "=?", new String[] { uid } );
    }


    /**
     * 执行SQL <br>
     * Created 2014年9月16日 上午12:16:04
     * 
     * @param sql
     *            sql语句
     * @author wat.ztag
     */
    private void execSql(String sql) {
        Log.d(sql);
        mDb.execSQL(sql);
    }
    
    /**
     * 
     * <br>Created 2014年11月28日 上午12:05:46
     * @author       wat.ztag
    */
    @Override
    public void initMagicNumber() {
    }
}
